package gcache

import (
	"context"
	"fmt"
	"gocamp2022/shutdown/daos"
	"log"
	"runtime"
	"sync"
	"sync/atomic"
	"time"
)

var Gcache sync.Map

// BrushCacheToDB 将缓存中的数据写入数据库
func BrushCacheToDB() error {
	log.Println("将缓存中的数据写入数据库开始")
	var total, suss, fail uint64
	t0 := time.Now()

	defer func() {
		log.Printf("将缓存中的数据写入数据库结束 total:%d succ:%d fail:%d timeused:%v\n", total, suss, fail, time.Since(t0))
	}()

	// 创建协程来处理缓存中的数据
	datasChan := make(chan [2]interface{}, 1024)

	go func() {
		// 遍历缓存中的数据
		Gcache.Range(func(key, value interface{}) bool {
			// 将数据写入数据库
			datasChan <- [2]interface{}{key, value}
			total++
			return true
		})

		close(datasChan)
	}()

	// 创建协程来处理数据库中的数据
	var wg sync.WaitGroup
	wg.Add(runtime.NumCPU())

	for i := 0; i < runtime.NumCPU(); i++ {
		go func() {
			defer wg.Done()

			dao := daos.NewCacheDao()
			for data := range datasChan {
				k := fmt.Sprintf("%v", data[0])
				v := fmt.Sprintf("%v", data[1])
				// 将数据写入数据库
				if err := dao.InsertOrUpdate(context.Background(), k, v); err != nil {
					log.Printf("写入数据库失败:%v\n", err)
					atomic.AddUint64(&fail, 1)
				} else {
					atomic.AddUint64(&suss, 1)
				}
			}
		}()
	}

	wg.Wait()

	log.Println("同步缓存到数据库完成")

	return nil
}
